using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace CSharpBasicsExamples.AOP
{
    // AOP 示例：使用 Attribute 实现横切关注点
    
    // 1. 日志记录 Attribute
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
    public class LogAttribute : Attribute
    {
        public string LogLevel { get; set; } = "INFO";
        public bool LogParameters { get; set; } = true;
        public bool LogReturnValue { get; set; } = true;
        public bool LogExecutionTime { get; set; } = true;
        
        public LogAttribute() { }
        
        public LogAttribute(string logLevel)
        {
            LogLevel = logLevel;
        }
    }
    
    // 2. 性能监控 Attribute
    [AttributeUsage(AttributeTargets.Method)]
    public class PerformanceMonitorAttribute : Attribute
    {
        public int WarningThresholdMs { get; set; } = 1000;
        public bool AlertOnSlowExecution { get; set; } = true;
        
        public PerformanceMonitorAttribute() { }
        
        public PerformanceMonitorAttribute(int warningThresholdMs)
        {
            WarningThresholdMs = warningThresholdMs;
        }
    }
    
    // 3. 缓存 Attribute
    [AttributeUsage(AttributeTargets.Method)]
    public class CacheAttribute : Attribute
    {
        public int CacheDurationMinutes { get; set; } = 5;
        public string CacheKey { get; set; }
        
        public CacheAttribute() { }
        
        public CacheAttribute(int cacheDurationMinutes)
        {
            CacheDurationMinutes = cacheDurationMinutes;
        }
    }
    
    // 4. 权限验证 Attribute
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
    public class AuthorizeAttribute : Attribute
    {
        public string[] Roles { get; set; }
        public string Permission { get; set; }
        
        public AuthorizeAttribute() { }
        
        public AuthorizeAttribute(params string[] roles)
        {
            Roles = roles;
        }
    }
    
    // AOP 拦截器接口
    public interface IMethodInterceptor
    {
        void BeforeMethod(MethodInfo method, object[] args);
        void AfterMethod(MethodInfo method, object[] args, object result, TimeSpan executionTime);
        void OnException(MethodInfo method, object[] args, Exception exception);
    }
    
    // 日志拦截器实现
    public class LoggingInterceptor : IMethodInterceptor
    {
        public void BeforeMethod(MethodInfo method, object[] args)
        {
            var logAttr = method.GetCustomAttribute<LogAttribute>();
            if (logAttr == null) return;
            
            Console.WriteLine($"[{logAttr.LogLevel}] 开始执行方法: {method.DeclaringType?.Name}.{method.Name}");
            
            if (logAttr.LogParameters && args.Length > 0)
            {
                Console.WriteLine($"[{logAttr.LogLevel}] 参数: [{string.Join(", ", args)}]");
            }
        }
        
        public void AfterMethod(MethodInfo method, object[] args, object result, TimeSpan executionTime)
        {
            var logAttr = method.GetCustomAttribute<LogAttribute>();
            if (logAttr == null) return;
            
            Console.WriteLine($"[{logAttr.LogLevel}] 方法执行完成: {method.DeclaringType?.Name}.{method.Name}");
            
            if (logAttr.LogReturnValue && result != null)
            {
                Console.WriteLine($"[{logAttr.LogLevel}] 返回值: {result}");
            }
            
            if (logAttr.LogExecutionTime)
            {
                Console.WriteLine($"[{logAttr.LogLevel}] 执行时间: {executionTime.TotalMilliseconds:F2} ms");
            }
        }
        
        public void OnException(MethodInfo method, object[] args, Exception exception)
        {
            var logAttr = method.GetCustomAttribute<LogAttribute>();
            var logLevel = logAttr?.LogLevel ?? "ERROR";
            
            Console.WriteLine($"[{logLevel}] 方法执行异常: {method.DeclaringType?.Name}.{method.Name}");
            Console.WriteLine($"[{logLevel}] 异常信息: {exception.Message}");
        }
    }
    
    // 性能监控拦截器
    public class PerformanceInterceptor : IMethodInterceptor
    {
        public void BeforeMethod(MethodInfo method, object[] args)
        {
            // 性能监控在 AfterMethod 中处理
        }
        
        public void AfterMethod(MethodInfo method, object[] args, object result, TimeSpan executionTime)
        {
            var perfAttr = method.GetCustomAttribute<PerformanceMonitorAttribute>();
            if (perfAttr == null) return;
            
            var executionMs = executionTime.TotalMilliseconds;
            
            if (executionMs > perfAttr.WarningThresholdMs && perfAttr.AlertOnSlowExecution)
            {
                Console.WriteLine($"[PERFORMANCE WARNING] 方法 {method.Name} 执行时间过长: {executionMs:F2} ms (阈值: {perfAttr.WarningThresholdMs} ms)");
            }
            else
            {
                Console.WriteLine($"[PERFORMANCE] 方法 {method.Name} 执行时间: {executionMs:F2} ms");
            }
        }
        
        public void OnException(MethodInfo method, object[] args, Exception exception)
        {
            Console.WriteLine($"[PERFORMANCE ERROR] 方法 {method.Name} 执行异常，无法统计性能");
        }
    }
    
    // 简单的方法执行器（模拟 AOP 框架）
    public static class MethodExecutor
    {
        private static readonly IMethodInterceptor[] Interceptors = 
        {
            new LoggingInterceptor(),
            new PerformanceInterceptor()
        };
        
        public static T ExecuteWithAOP<T>(Func<T> method, [CallerMemberName] string methodName = "")
        {
            var methodInfo = method.Method;
            var args = new object[0]; // 简化示例，实际应该获取真实参数
            
            // Before 拦截
            foreach (var interceptor in Interceptors)
            {
                try
                {
                    interceptor.BeforeMethod(methodInfo, args);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"拦截器 BeforeMethod 异常: {ex.Message}");
                }
            }
            
            var stopwatch = Stopwatch.StartNew();
            T result = default(T);
            Exception executionException = null;
            
            try
            {
                // 执行原方法
                result = method();
            }
            catch (Exception ex)
            {
                executionException = ex;
            }
            finally
            {
                stopwatch.Stop();
            }
            
            // After 拦截
            foreach (var interceptor in Interceptors)
            {
                try
                {
                    if (executionException == null)
                    {
                        interceptor.AfterMethod(methodInfo, args, result, stopwatch.Elapsed);
                    }
                    else
                    {
                        interceptor.OnException(methodInfo, args, executionException);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"拦截器处理异常: {ex.Message}");
                }
            }
            
            // 如果原方法有异常，重新抛出
            if (executionException != null)
            {
                throw executionException;
            }
            
            return result;
        }
        
        public static void ExecuteWithAOP(Action method, [CallerMemberName] string methodName = "")
        {
            ExecuteWithAOP<object>(() => { method(); return null; }, methodName);
        }
    }
    
    // 业务服务类（应用 AOP）
    public class EmployeeService
    {
        [Log("INFO", LogParameters = true, LogReturnValue = true)]
        [PerformanceMonitor(500)]
        public Employee GetEmployeeById(int id)
        {
            return MethodExecutor.ExecuteWithAOP(() =>
            {
                // 模拟数据库查询延迟
                System.Threading.Thread.Sleep(300);
                
                return new Employee
                {
                    Id = id,
                    Name = $"员工{id}",
                    Department = "IT部门",
                    Salary = 8000 + id * 100
                };
            });
        }
        
        [Log("DEBUG")]
        [PerformanceMonitor(1000)]
        public void UpdateEmployee(Employee employee)
        {
            MethodExecutor.ExecuteWithAOP(() =>
            {
                // 模拟数据库更新操作
                System.Threading.Thread.Sleep(200);
                Console.WriteLine($"更新员工信息: {employee.Name}");
            });
        }
        
        [Log("WARN")]
        [PerformanceMonitor(100)] // 设置较低阈值来触发警告
        public decimal CalculateBonus(int employeeId, decimal baseSalary)
        {
            return MethodExecutor.ExecuteWithAOP(() =>
            {
                // 模拟复杂计算
                System.Threading.Thread.Sleep(150);
                return baseSalary * 0.1m;
            });
        }
        
        [Log("ERROR")]
        public void ProcessPayroll()
        {
            MethodExecutor.ExecuteWithAOP(() =>
            {
                Console.WriteLine("开始处理薪资...");
                // 模拟异常情况
                throw new InvalidOperationException("薪资处理系统暂时不可用");
            });
        }
    }
    
    // 员工实体类
    public class Employee
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Department { get; set; }
        public decimal Salary { get; set; }
        
        public override string ToString()
        {
            return $"Employee(Id={Id}, Name={Name}, Department={Department}, Salary={Salary:C})";
        }
    }
    
    // AOP 演示程序
    public class AOPDemo
    {
        public static void RunDemo()
        {
            Console.WriteLine("=== AOP (面向切面编程) 演示 ===\n");
            
            var employeeService = new EmployeeService();
            
            try
            {
                Console.WriteLine("1. 查询员工信息（正常执行）:");
                var employee = employeeService.GetEmployeeById(1001);
                Console.WriteLine($"查询结果: {employee}\n");
                
                Console.WriteLine("2. 更新员工信息:");
                employeeService.UpdateEmployee(new Employee 
                { 
                    Id = 1001, 
                    Name = "张三", 
                    Department = "研发部", 
                    Salary = 9000 
                });
                Console.WriteLine();
                
                Console.WriteLine("3. 计算奖金（触发性能警告）:");
                var bonus = employeeService.CalculateBonus(1001, 8000);
                Console.WriteLine($"计算的奖金: {bonus:C}\n");
                
                Console.WriteLine("4. 处理薪资（异常情况）:");
                employeeService.ProcessPayroll();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"捕获到异常: {ex.Message}\n");
            }
            
            Console.WriteLine("=== AOP 演示完成 ===");
            Console.WriteLine("\nAOP 的优势:");
            Console.WriteLine("1. 关注点分离：业务逻辑与横切关注点分离");
            Console.WriteLine("2. 代码复用：日志、性能监控等逻辑可重用");
            Console.WriteLine("3. 维护性：修改横切逻辑不影响业务代码");
            Console.WriteLine("4. 可读性：业务代码更加清晰简洁");
        }
    }
}
